package server.exchange;

import java.util.ArrayList;
import java.util.List;

import server.thread.ListenerThread;

public class OrderNamedColection {
	private String stockName;
	private int currentId=0;
	private static int ID_RANGE=10;
	
	private List <Order> sellOrders=new ArrayList<Order>();
	private List <Order> buyOrders=new ArrayList<Order>();
	private List <Order> waitingOrders=new ArrayList<Order>();
	
	private class InputOrdersHandler extends Thread{

		@Override
		public void run() {
			while(true){
				synchronized (waitingOrders){
					while (waitingOrders.size()==0){
						try{
							waitingOrders.wait();
							
						} catch (InterruptedException e){
							//TODO ADD LOG
						}
					}
//					synchronized (buyOrders) {
//						synchronized (sellOrders) {
//							
//						}
//						
//					}
					addOrder(waitingOrders.get(0));
					waitingOrders.remove(0);
				}
			}
		}
		
	}
	private InputOrdersHandler ordersHandler=new InputOrdersHandler();
	
	
	public OrderNamedColection(Order order){
		this.stockName=order.getStockName();
		addOrder(order);
		ordersHandler.start();
	}
	public OrderNamedColection(String name){
		this.stockName=name;
		ordersHandler.start();
	}
	
	private void addBuyOrder(Order order){
		buyOrders.add(order);
		try{
			Buyer.tryBuy(sellOrders, order);
		} catch (InterruptedException e) {
			
		}
	}
	
	
	
	private void addSellOrder(Order order){
		sellOrders.add(order);
		try{
			Buyer.tryBuy(buyOrders, order);
		
			if (order.getStatus()!=ORDERSTATUS.EXECUTED){
				for (int i = 0; i < buyOrders.size(); i++) {
					if (buyOrders.get(i).getStatus()!=ORDERSTATUS.EXECUTED) Buyer.tryBuy(buyOrders.get(i), order);
				}
		}
		} catch (InterruptedException e) {
			
		}
	}

	public String getStockName() {
		return stockName;
	}
	
	private void addOrder(Order order){
		synchronized (this.buyOrders){
			synchronized (this.sellOrders){
		
				if (order.getOpperationType()==OPERATIONTYPE.BUY) {
					addBuyOrder(order);
				} else {
					addSellOrder(order);
				}
			}	
		}			
	}
	
	public void addOrderToQueue(Order order){
		synchronized (waitingOrders) {
			waitingOrders.add(order);
			waitingOrders.notify();
		}
	}
	
	public void addOrderWithoutOperations(Order order){
		if (order.getOpperationType()==OPERATIONTYPE.BUY) {
			buyOrders.add(order);
		} else {
			sellOrders.add(order);
		}
					
	}
	public void printOrders() {

		for (int i = 0; i < sellOrders.size(); i++) {
			System.out.println(sellOrders.get(i).toString());
		}
		for (int i = 0; i < buyOrders.size(); i++) {
			System.out.println(buyOrders.get(i).toString());
		}
	}
	
	public OrderNamedColection returnStockByClient(String clientName) {
		OrderNamedColection outputList=new OrderNamedColection(this.stockName);
		synchronized (sellOrders){
			for (int i = 0; i < sellOrders.size(); i++) {
				if (sellOrders.get(i).getClientName().equals(clientName)) outputList.addOrderWithoutOperations(sellOrders.get(i));
			}
		}
		synchronized (buyOrders){
			for (int i = 0; i < buyOrders.size(); i++) {
				if (buyOrders.get(i).getClientName().equals(clientName)) outputList.addOrderWithoutOperations(buyOrders.get(i));
			}
		}
		return outputList;
	}
	public void removeById(int id) {
	

			synchronized (sellOrders){
				for (int i = 0; i < sellOrders.size(); i++) {
					if (sellOrders.get(i).getId()==id) {
						sellOrders.get(i).setStatus(ORDERSTATUS.CANCEL);
						ServerExecutor.outOrdersHandler.execute(new ListenerThread(sellOrders.get(i).getMyself()));
					}
				}
			}
			synchronized (buyOrders){
				for (int i = 0; i < buyOrders.size(); i++) {
					if (buyOrders.get(i).getId()==id) {
						buyOrders.get(i).setStatus(ORDERSTATUS.CANCEL);
						ServerExecutor.outOrdersHandler.execute(new ListenerThread(buyOrders.get(i).getMyself()));
					}
				}
			}
	}
	
	public int getId(){
		this.currentId+=this.ID_RANGE;
		return (this.currentId-this.ID_RANGE);
	}
	public int getIdRange(){
		return this.ID_RANGE;
	}
}
